import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
import numpy as np
import os
import re
from matplotlib.font_manager import FontProperties
import jieba
from collections import Counter


# 设置中文字体支持
def set_chinese_font():
    """自动检测并设置可用的中文字体"""
    try:
        # 优先使用系统默认字体
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'STHeiti', 'SimSun']
        plt.rcParams['axes.unicode_minus'] = False
        sns.set(font='Microsoft YaHei')
        print("使用系统默认中文字体")
    except:
        try:
            font_path = None
            possible_fonts = [
                'C:/Windows/Fonts/simhei.ttf',  # Windows 黑体
                'C:/Windows/Fonts/msyh.ttc',  # Windows 微软雅黑
                'C:/Windows/Fonts/simsun.ttc',  # Windows 宋体
                '/System/Library/Fonts/PingFang.ttc',  # macOS 苹方
                '/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf'  # Linux
            ]

            for font in possible_fonts:
                if os.path.exists(font):
                    font_path = font
                    break

            if font_path:
                font_prop = FontProperties(fname=font_path)
                plt.rcParams['font.sans-serif'] = [font_prop.get_name()]
                plt.rcParams['axes.unicode_minus'] = False
                sns.set(font=font_prop.get_name())
                print(f"使用字体文件: {font_path}")
            else:
                print("警告: 未找到中文字体文件，尝试使用默认字体")
                plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
        except Exception as e:
            print(f"字体设置错误: {str(e)}")


set_chinese_font()


# 商品分类规则
def classify_product(product_name):
    """根据商品名称分类商品"""
    # 定义分类关键词
    categories = {
        '护肤品': ['洗面奶', '面膜', '精华', '乳液', '面霜', '眼霜', '防晒', '化妆水', '爽肤水', '护肤', '精华液',
                   '眼膜', '唇膏', '护手霜'],
        '服装': ['外套', '毛衣', 'T恤', '裤子', '裙子', '鞋', '帽', '卫衣', '内衣', '袜', '运动服', '牛仔裤', '羽绒服',
                 '衬衫', '夹克'],
        '学习用品': ['书', '笔', '本', '纸', '文具', '书包', '教材', '词典', '墨水', '练习册', '笔记本', '铅笔', '橡皮',
                     '尺子'],
        '电子产品': ['手机', '电脑', '平板', '耳机', '充电器', '数据线', '鼠标', '键盘', '显示器', '路由器', '充电宝'],
        '食品': ['零食', '饼干', '巧克力', '饮料', '牛奶', '咖啡', '茶', '水果', '坚果', '糖果', '方便面'],
        '家居用品': ['毛巾', '床单', '枕头', '被子', '厨具', '餐具', '清洁剂', '洗衣液', '垃圾桶', '收纳', '衣架'],
        '其他': []  # 默认分类
    }

    # 检查每个分类的关键词
    for category, keywords in categories.items():
        for keyword in keywords:
            if keyword in product_name:
                return category

    # 如果没有匹配到任何分类，返回"其他"
    return '其他'


def analyze_taobao_excel(filepath):
    # 1. 加载Excel数据
    try:
        df = pd.read_excel(filepath, parse_dates=['下单时间'])
        print("数据加载成功！前5行示例：")
        print(df.head())
    except Exception as e:
        print(f"数据加载失败：{str(e)}")
        return

    # 2. 数据清洗
    df['月份'] = df['下单时间'].dt.to_period('M')
    df['星期'] = df['下单时间'].dt.day_name()
    df['小时'] = df['下单时间'].dt.hour
    df['价格'] = pd.to_numeric(df['价格'], errors='coerce').fillna(0)

    # 3. 商品分类
    if '商品名称' in df.columns:
        print("\n正在根据商品名称进行分类...")
        df['商品类别'] = df['商品名称'].apply(classify_product)
        print("分类完成！商品类别分布：")
        print(df['商品类别'].value_counts())
    else:
        print("警告: 数据中缺少'商品名称'列，无法进行分类")
        return

    # 4. 可视化分析
    plt.figure(figsize=(18, 18))  # 增大图形尺寸以容纳更多图表

    # 4.1 消费金额趋势
    plt.subplot(3, 2, 1)
    monthly_sales = df.groupby('月份')['价格'].sum()

    if not monthly_sales.empty:
        monthly_sales.index = monthly_sales.index.astype(str)
        monthly_sales.plot(kind='bar', color='#FF6B6B')
        plt.title('月度消费趋势', pad=20)
        plt.ylabel('消费金额 (元)')
        plt.xticks(rotation=45)
    else:
        plt.text(0.5, 0.5, '无月度消费数据', ha='center', va='center', fontsize=14)
        plt.title('月度消费趋势 (无数据)', pad=20)
        plt.axis('off')

    # 4.2 支付方式占比
    plt.subplot(3, 2, 2)
    df['支付方式'] = df['支付方式'].fillna('未知')
    payment = df['支付方式'].value_counts()

    if not payment.empty:
        plt.pie(payment, labels=payment.index, autopct='%1.1f%%',
                colors=['#4CCD99', '#FFC700', '#7B66FF', '#FF6B6B', '#C70039'])
        plt.title('支付方式分布', pad=20)
    else:
        plt.text(0.5, 0.5, '无支付方式数据', ha='center', va='center', fontsize=14)
        plt.title('支付方式分布 (无数据)', pad=20)
        plt.axis('off')

    # 4.3 消费时段热力图
    plt.subplot(3, 2, 3)
    if '小时' in df.columns and '星期' in df.columns:
        hour_week = pd.crosstab(df['小时'], df['星期'])
        if not hour_week.empty:
            sns.heatmap(hour_week, cmap='Blues', annot=True, fmt='d', cbar_kws={'label': '交易次数'})
            plt.title('消费时段分布', pad=20)
            plt.xlabel('星期')
            plt.ylabel('小时')
        else:
            plt.text(0.5, 0.5, '无消费时段数据', ha='center', va='center', fontsize=14)
            plt.title('消费时段分布 (无数据)', pad=20)
            plt.axis('off')
    else:
        plt.text(0.5, 0.5, '缺少小时或星期数据', ha='center', va='center', fontsize=14)
        plt.title('消费时段分布 (数据缺失)', pad=20)
        plt.axis('off')

    # 4.4 商品类别消费占比
    plt.subplot(3, 2, 4)
    if '商品类别' in df.columns:
        category_sales = df.groupby('商品类别')['价格'].sum()
        if not category_sales.empty:
            # 确保没有NaN值
            category_sales = category_sales.fillna(0)

            # 过滤掉值为0的类别
            category_sales = category_sales[category_sales > 0]

            if not category_sales.empty:
                # 按金额排序
                category_sales = category_sales.sort_values(ascending=False)

                # 创建饼图
                plt.pie(category_sales, labels=category_sales.index, autopct='%1.1f%%',
                        colors=plt.cm.tab20.colors)
                plt.title('商品类别消费占比', pad=20)
            else:
                plt.text(0.5, 0.5, '所有类别消费金额均为0', ha='center', va='center', fontsize=14)
                plt.title('商品类别消费占比 (无有效数据)', pad=20)
                plt.axis('off')
        else:
            plt.text(0.5, 0.5, '无商品类别消费数据', ha='center', va='center', fontsize=14)
            plt.title('商品类别消费占比 (无数据)', pad=20)
            plt.axis('off')
    else:
        plt.text(0.5, 0.5, '无商品类别数据', ha='center', va='center', fontsize=14)
        plt.title('商品类别消费占比 (数据缺失)', pad=20)
        plt.axis('off')

    # 4.5 商品类别词云（基于分类）
    plt.subplot(3, 2, 5)
    if '商品类别' in df.columns:
        # 生成类别频率字典
        category_counts = df['商品类别'].value_counts().to_dict()

        try:
            # 获取中文字体路径
            font_path = None
            possible_fonts = [
                'C:/Windows/Fonts/simhei.ttf',
                'C:/Windows/Fonts/msyh.ttc',
                'C:/Windows/Fonts/simsun.ttc',
                '/System/Library/Fonts/PingFang.ttc',
                '/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf'
            ]

            for font in possible_fonts:
                if os.path.exists(font):
                    font_path = font
                    break

            # 创建词云
            wordcloud = WordCloud(
                font_path=font_path,  # 关键修复：明确指定字体路径
                background_color='white',
                colormap='tab20',
                width=800,
                height=600,
                max_words=100
            ).generate_from_frequencies(category_counts)

            plt.imshow(wordcloud, interpolation='bilinear')
            plt.axis('off')
            plt.title('商品类别词云', pad=20)
        except Exception as e:
            print(f"词云生成失败: {str(e)}")
            plt.text(0.5, 0.5, f'词云生成失败: {str(e)}', ha='center', va='center', fontsize=10)
            plt.axis('off')
            plt.title('商品类别词云 (生成失败)', pad=20)
    else:
        plt.text(0.5, 0.5, '无商品类别数据', ha='center', va='center', fontsize=14)
        plt.axis('off')
        plt.title('商品类别词云 (数据缺失)', pad=20)

    # 4.6 商品名称关键词词云
    plt.subplot(3, 2, 6)
    if '商品名称' in df.columns:
        # 合并所有商品名称文本
        text = ' '.join(df['商品名称'].dropna().astype(str))

        if text.strip():
            try:
                # 获取中文字体路径
                font_path = None
                possible_fonts = [
                    'C:/Windows/Fonts/simhei.ttf',
                    'C:/Windows/Fonts/msyh.ttc',
                    'C:/Windows/Fonts/simsun.ttc',
                    '/System/Library/Fonts/PingFang.ttc',
                    '/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf'
                ]

                for font in possible_fonts:
                    if os.path.exists(font):
                        font_path = font
                        break

                # 使用jieba分词
                words = jieba.cut(text)
                word_list = [word for word in words if len(word) > 1]  # 过滤单字
                word_freq = Counter(word_list)

                # 创建词云
                wordcloud = WordCloud(
                    font_path=font_path,  # 关键修复：明确指定字体路径
                    background_color='white',
                    colormap='tab20',
                    width=800,
                    height=600,
                    max_words=100
                ).generate_from_frequencies(word_freq)

                plt.imshow(wordcloud, interpolation='bilinear')
                plt.axis('off')
                plt.title('商品名称关键词词云', pad=20)
            except Exception as e:
                print(f"词云生成失败: {str(e)}")
                plt.text(0.5, 0.5, f'词云生成失败: {str(e)}', ha='center', va='center', fontsize=10)
                plt.axis('off')
                plt.title('商品名称关键词词云 (生成失败)', pad=20)
        else:
            plt.text(0.5, 0.5, '商品名称数据为空', ha='center', va='center', fontsize=14)
            plt.axis('off')
            plt.title('商品名称关键词词云 (数据为空)', pad=20)
    else:
        plt.text(0.5, 0.5, '无商品名称数据', ha='center', va='center', fontsize=14)
        plt.axis('off')
        plt.title('商品名称关键词词云 (数据缺失)', pad=20)

    plt.tight_layout()
    plt.savefig('淘宝消费分析报告.png', dpi=300, bbox_inches='tight')
    print("\n分析完成！结果已保存为：淘宝消费分析报告.png")


# 使用示例
if __name__ == "__main__":
    # 分析实际数据
    analyze_taobao_excel(r"C:\Users\Lenovo\OneDrive\桌面\订单数据.xlsx")
